package com.xh.chat.netty.utils;

import com.xh.chat.utils.JsonUtils;
import io.netty.channel.Channel;
import io.netty.channel.ChannelId;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.util.concurrent.GlobalEventExecutor;
import lombok.extern.slf4j.Slf4j;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author wen
 * @apiNote ChannelUtil
 * @since 2021-08-09
 */
@Slf4j
public class ChannelUtil {

    /**
     * 用于记录和管理所有客户端的channel
     */
    public static final ChannelGroup USER_CHANNEL_GROUP = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);

    /**
     * 用户ID和Channel关系MAP
     */
    private static final Map<Long, Channel> USER_CHANNEL_RELATION = new ConcurrentHashMap<>();

    public static void put(Long senderId, Channel channel) {
        USER_CHANNEL_RELATION.put(senderId, channel);
    }

    public static Channel get(Long senderId) {
        return USER_CHANNEL_RELATION.get(senderId);
    }

    public static void output() {
        for (HashMap.Entry<Long, Channel> entry : USER_CHANNEL_RELATION.entrySet()) {
            log.info("UserId: " + entry.getKey()
                    + ", ChannelId: " + entry.getValue().id().asLongText());
        }
    }

    public static Channel getChannel(ChannelId id) {
        return USER_CHANNEL_GROUP.find(id);
    }

    /**
     * 通过用户ID发送消息
     */
    public static void sendByUserId(Long userId, Object msg) {
        Channel receiverChannel = ChannelUtil.get(userId);
        if (receiverChannel == null) {
            // TODO channel为空代表用户离线，推送消息（JPush，个推，小米推送）
        } else {
            sendByChannelId(receiverChannel.id(), msg);
        }
    }

    /**
     * 通过ChannelId发送消息
     */
    public static void sendByChannelId(ChannelId id, Object msg) {
        // 当receiverChannel不为空的时候，从ChannelGroup去查找对应的channel是否存在
        Channel channel = USER_CHANNEL_GROUP.find(id);
        if (channel != null) {
            String message;
            if (msg instanceof String) {
                message = msg.toString();
            } else {
                message = JsonUtils.objectToJson(msg);
            }
            // 用户在线
            channel.writeAndFlush(new TextWebSocketFrame(message));
        } else {
            // 用户离线 TODO 推送消息
        }
    }

}
